#include <iostream>
#include <fstream>
#include "pb_cfg_reward.pb.h"
#include "CWorldBossMgr.h"
#include "MsgBattle.pb.h"
#include "MsgWorldBoss.pb.h"
#include "commmsg.h"
#include "../simpleconfig/CMonsterConfig.h"
#include "../data/CPlayerCacheData.h"
#include "../status/CUserStatus.h"
#include "../battle/CBattleRole.h"
#include "../battle/CBattleMgr.h"
#include "../map/CMapView.h"
#include "../act/CActCfg.h"
#include "../mainctrl.h"
#include "CTRandomNum.h"
#include "MsgGM.pb.h"
#include "CTSizeString.h"

int CWorldBossMgr::LoadConfig(const char* szCfgPath)
{
    int iRet = 0;

    if (NULL == szCfgPath)
    {
        CT_ERROR(("Reward Cfg Path is null"));
        return RET_SYSTEM_FAIL;
    }

    pb_cfg_reward stRewardCfg;
    std::fstream stFileInput(szCfgPath, std::ios::in | std::ios::binary);
    if (!stRewardCfg.ParseFromIstream(&stFileInput))
    {
        CT_ERROR(("Failed to Parse RewardCfg!"));
        return RET_SYSTEM_FAIL;
    }

    //需且仅需显式调用一次
    CMainCtrl::m_pstMain->m_stWorldBossMgr.InitWorldBossCfg();

    CWorldBossCfgAttack stAttackData;
    for (int i = 0; i < stRewardCfg.boss_base_reward_rows_size(); ++i)
    {
        const pb_cfg_reward_pb_cfg_boss_base_reward_unit& stAttackUnit 
            = stRewardCfg.boss_base_reward_rows(i);

        stAttackData.Clear();

        stAttackData.SetAttackID(stAttackUnit.attack_id());
        stAttackData.SetReputationBase(stAttackUnit.reputation_ratio());
        stAttackData.SetExpBase(stAttackUnit.exp_ratio());
        stAttackData.SetContribuBase(stAttackUnit.contribu_ratio());
        stAttackData.SetSilverBase(stAttackUnit.silver_ratio());

        iRet = CMainCtrl::m_pstMain->m_stWorldBossMgr.AddAttackConfig(
            stAttackData);
        CT_RETURN(iRet);
    }

#define MAX_MAGIC_DOOR_GIFT_COUNT 12
    CTLib::CTArray<int, MAX_WORLD_BOSS_GIFT_COUNT> aiGiftCfgID;
    CTLib::CTArray<int, MAX_ACADEMY_BOSS_GIFT_COUNT> aiAcademyGiftCfgID;
    CTLib::CTArray<int, MAX_MAGIC_DOOR_GIFT_COUNT> aiMagicDoorGiftCfgID;

    CWorldBossCfgReward stRewardData;
    for (int i = 0; i < stRewardCfg.boss_level_reward_rows_size(); ++i)
    {
        const pb_cfg_reward_pb_cfg_boss_level_reward_unit& stRewardUnit 
            = stRewardCfg.boss_level_reward_rows(i);

        stRewardData.Clear();

        aiGiftCfgID.Clear();
        aiAcademyGiftCfgID.Clear();
        aiMagicDoorGiftCfgID.Clear();

        stRewardData.SetLevel(stRewardUnit.level());
        stRewardData.SetReputationRatio(stRewardUnit.reputation_ratio());
        stRewardData.SetExpRatio(stRewardUnit.exp_ratio());
        stRewardData.SetContribuRatio(stRewardUnit.contribu_ratio());
        stRewardData.SetSilverRatio(stRewardUnit.silver_ratio());
        stRewardData.SetFiftyReputation(stRewardUnit.fifty_reputation());
        stRewardData.SetFiftyExp(stRewardUnit.fifty_exp());
        stRewardData.SetFiftyContribu(stRewardUnit.fifty_contribu());
        stRewardData.SetFiftySilver(stRewardUnit.fifty_silver());
        stRewardData.SetKillReputation(stRewardUnit.kill_reputation());
        stRewardData.SetKillExp(stRewardUnit.kill_exp());
        stRewardData.SetKillContribu(stRewardUnit.kill_contribu());
        stRewardData.SetKillSilver(stRewardUnit.kill_silver());
        stRewardData.SetRewardBackWorldBoss(
            stRewardUnit.reward_back_worldboss());
        stRewardData.SetRewardBackAcademyBoss(
            stRewardUnit.reward_back_academyboss());
        stRewardData.SetRewardBackEnemyCity(
            stRewardUnit.reward_back_enemycity());

        aiGiftCfgID.AddOneItem(stRewardUnit.gift_1());
        aiGiftCfgID.AddOneItem(stRewardUnit.gift_2());
        aiGiftCfgID.AddOneItem(stRewardUnit.gift_3());
        aiGiftCfgID.AddOneItem(stRewardUnit.gift_4());
        aiGiftCfgID.AddOneItem(stRewardUnit.gift_5());
        aiGiftCfgID.AddOneItem(stRewardUnit.gift_6());
        aiGiftCfgID.AddOneItem(stRewardUnit.gift_7());
        aiGiftCfgID.AddOneItem(stRewardUnit.gift_8());
        aiGiftCfgID.AddOneItem(stRewardUnit.gift_9());
        aiGiftCfgID.AddOneItem(stRewardUnit.gift_10());

        stRewardData.SetAcademyReputation(stRewardUnit.academy_reputation());
        stRewardData.SetAcademyExp(stRewardUnit.academy_exp());
        stRewardData.SetAcademyContribu(stRewardUnit.academy_contribu());
        stRewardData.SetAcademySilver(stRewardUnit.academy_silver());
        stRewardData.SetAcademyFootboyReputation(
            stRewardUnit.academy_footboy_reputation());
        stRewardData.SetAcademyFootboyExp(stRewardUnit.academy_footboy_exp());
        stRewardData.SetAcademyFootboyContribu(
            stRewardUnit.academy_footboy_contribu());
        stRewardData.SetAcademyFootboySilver(
            stRewardUnit.academy_footboy_silver());
        stRewardData.SetAcademyFiftyReputation(
            stRewardUnit.academy_fifty_reputation());
        stRewardData.SetAcademyFiftyExp(stRewardUnit.academy_fifty_exp());
        stRewardData.SetAcademyFiftyContribu(
            stRewardUnit.academy_fifty_contribu());
        stRewardData.SetAcademyFiftySilver(stRewardUnit.academy_fifty_silver());
        stRewardData.SetAcademyKillReputation(
            stRewardUnit.academy_kill_reputation());
        stRewardData.SetAcademyKillExp(stRewardUnit.academy_kill_exp());
        stRewardData.SetAcademyKillContribu(
            stRewardUnit.academy_kill_contribu());
        stRewardData.SetAcademyKillSilver(stRewardUnit.academy_kill_silver());

        aiAcademyGiftCfgID.AddOneItem(stRewardUnit.academy_gift_1());
        aiAcademyGiftCfgID.AddOneItem(stRewardUnit.academy_gift_2());
        aiAcademyGiftCfgID.AddOneItem(stRewardUnit.academy_gift_3());
        aiAcademyGiftCfgID.AddOneItem(stRewardUnit.academy_gift_4());
        aiAcademyGiftCfgID.AddOneItem(stRewardUnit.academy_gift_5());
        aiAcademyGiftCfgID.AddOneItem(stRewardUnit.academy_gift_6());
        aiAcademyGiftCfgID.AddOneItem(stRewardUnit.academy_gift_7());
        aiAcademyGiftCfgID.AddOneItem(stRewardUnit.academy_gift_8());
        aiAcademyGiftCfgID.AddOneItem(stRewardUnit.academy_gift_9());
        aiAcademyGiftCfgID.AddOneItem(stRewardUnit.academy_gift_10());

        stRewardData.SetMagicDoorReputation(
            stRewardUnit.magicdoor_reputation());
        stRewardData.SetMagicDoorExp(stRewardUnit.magicdoor_exp());
        stRewardData.SetMagicDoorContribu(stRewardUnit.magicdoor_contribu());
        stRewardData.SetMagicDoorSilver(stRewardUnit.magicdoor_silver());

        stRewardData.SetMagicDoorKillGift(stRewardUnit.magicdoor_kill_gift());
        stRewardData.SetMagicDoorKillSpeGift(
            stRewardUnit.magicdoor_special_kill_gift());

        if (!stRewardData.IsValidData())
        {
            CT_RETURN(ERROR_WORLD_BOSS_REWARD_DATA);
        }

        aiMagicDoorGiftCfgID.AddOneItem(stRewardData.GetMagicDoorKillGift());
        aiMagicDoorGiftCfgID.AddOneItem(stRewardData.GetMagicDoorKillSpeGift());

        for (int i = 0; i < aiGiftCfgID.Size(); ++i)
        {
            if (aiGiftCfgID[i] > 0)
            {
                if (!CMainCtrl::m_pstMain->m_stItemMgr.IsGiftValid(
                        (unsigned int)aiGiftCfgID[i]))
                {
                    CT_RETURN(ERROR_GIFT_CONFIG_NONE);
                }
                stRewardData.AddGiftID(aiGiftCfgID[i]);
            }
        }

        for (int i = 0; i < aiAcademyGiftCfgID.Size(); ++i)
        {
            if (aiAcademyGiftCfgID[i] > 0)
            {
                if (!CMainCtrl::m_pstMain->m_stItemMgr.IsGiftValid(
                        (unsigned int)aiAcademyGiftCfgID[i]))
                {
                    CT_RETURN(ERROR_GIFT_CONFIG_NONE);
                }
                stRewardData.AddAcademyGiftID(aiAcademyGiftCfgID[i]);
            }
        }

        for (int i = 0; i < aiMagicDoorGiftCfgID.Size(); ++i)
        {
            if (aiMagicDoorGiftCfgID[i] > 0)
            {
                if (!CMainCtrl::m_pstMain->m_stItemMgr.IsGiftValid(
                        (unsigned int)aiMagicDoorGiftCfgID[i]))
                {
                    CT_RETURN(ERROR_GIFT_CONFIG_NONE);
                }
            }
        }

        stRewardData._iEacSilverBonus = stRewardUnit.eac_silver_bonus();
        stRewardData._iEacExpBonus = stRewardUnit.eac_exp_bonus();

        iRet = CMainCtrl::m_pstMain->m_stWorldBossMgr.AddRewardConfig(
            stRewardData);
        CT_RETURN(iRet);
    }

    return 0;
}

bool CWorldBossMgr::IsMapIDNeedUpdateDB(const unsigned int uiMapID)
{
    if (GetWorldBossMapID() == uiMapID)//世界Boss地图场景不保存DB
    {
        return false;
    }

    return true;
}

//进入世界BOSS场景
int CWorldBossMgr::EnterScene(const unsigned int uiMapID, unsigned int uiGID)
{
    if (GetWorldBossMapID() != uiMapID)
    {
        return 0;
    }

    if (CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(
            GetWorldBossMapID(), uiGID))
    {
        //已经在场景内的不限制
        return 0;
    }

    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(ACT_ID_WORLD_BOSS))
    {
        //非活动期间不允许进入
        return ERROR_WORLD_BOSS_ACT_NO_OPEN;
    }

    return 0;
}

//离开世界BOSS场景
int CWorldBossMgr::LeaveScene()
{
    return 0;
}

//活动开启
//必须通过引用的方式将活动实体传过来而不能再在内部find活动
int CWorldBossMgr::ActOpen(CActCfgData& stActCfgData)
{
    int iRet = 0;
    int iIndex = 0;

    iIndex = CMainCtrl::m_pstMain->m_stSceneMgr.FindSceneCfg(
        stActCfgData.GetSceneID());
    if (iIndex < 0)
    {
        CT_WARNING(("world boss scene(%d) config in act(%d) empty!",
                    stActCfgData.GetSceneID(),ACT_ID_WORLD_BOSS));
        return ERROR_SCENE_EMPTY_CFG;
    }
    CSceneCfgData& stSceneCfgData =
        CMainCtrl::m_pstMain->m_stSceneMgr.GetSceneCfg(iIndex);

    _stWorldBossMonster.Clear();

    _stWorldBossMonster.SetMapID(stSceneCfgData.GetMapID());
    _stWorldBossMonster.SetEndTime(stActCfgData.GetEndTime());
    _stWorldBossMonster.SetMonsterGroupID(stSceneCfgData.GetMonGroupID());

    _stWorldBossMonster.SetWorldLevel(
        CMainCtrl::m_pstMain->m_stArenaMgr.GetWorldBossLevel());

    _stWorldBossMonster.SetMonsterBornTime(
        stActCfgData.GetBeginTime() + WORLD_BOSS_MONSTER_BORN_TIME);

    CMonsterGroupConfigData stMonsterGroup;
    iRet = CMainCtrl::m_pstMain->m_stMonsterConfigMgr.GetMonsterGroupConfig(
        _stWorldBossMonster.GetMonsterGroupID(),
        _stWorldBossMonster.GetWorldLevel(), stMonsterGroup);
    CT_RETURN(iRet);

    //设置怪物信息
    _stWorldBossMonster.SetMonsterHP(
        stMonsterGroup._astMonsters[0]._stMonster._stMonsterDefaultAttr._uiHP);
    _stWorldBossMonster.SetMonsterHPMax(
        stMonsterGroup._astMonsters[0]._stMonster._stMonsterDefaultAttr._uiHP);

    int64 i64TriggerVal =
        stMonsterGroup._astMonsters[0]._stMonster._stMonsterDefaultAttr._uiHP *
            INT64_1 * WORLD_BOSS_INSPIRE_TRIGGER / BATTLE_RATE_SKILL_PERCENT;
    _stWorldBossMonster.SetInspireTrigger((int)(i64TriggerVal));

    CT_TRACE(("world boss map id (%d) end time(%d)" \
              " monster hp(%d) inspire trigger(%d)",
              _stWorldBossMonster.GetMapID(),
              _stWorldBossMonster.GetEndTime(),
              _stWorldBossMonster.GetMonsterHP(),
              _stWorldBossMonster.GetInspireTrigger()));

    CMainCtrl::m_pstMain->m_stRewardBackMgr.SetActOpen(ACT_ID_WORLD_BOSS,
        _stWorldBossMonster.GetWorldLevel());
    
    return 0;
}

//活动自然关闭
int CWorldBossMgr::ActClose(CActCfgData& stActCfgData)
{
    //下发排名榜给场景内所有角色
    WorldBossSceneNotify();

    //发放奖励礼包
    WorldBossFinishReward();   

    WorldBossNotifyTips(TIPS_WORLD_BOSS_RANK);//全服提示走马灯

    return 0;
}

unsigned int CWorldBossMgr::GetWorldBossMapID()
{
    int iIndex = 0;
    if (_stWorldBossMonster.GetMapID() <= 0)
    {
        iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActCfg(
            ACT_ID_WORLD_BOSS);
        if (iIndex < 0)
        {
            CT_WARNING(("world boss act(%d) config empty!",
                        ACT_ID_WORLD_BOSS));
            return 0;
        }
        CActCfgData& stActCfgData =
            CMainCtrl::m_pstMain->m_stActMgr.GetActCfg(iIndex);

        iIndex = CMainCtrl::m_pstMain->m_stSceneMgr.FindSceneCfg(
            stActCfgData.GetSceneID());
        if (iIndex < 0)
        {
            CT_WARNING(("world boss scene(%d) config in act(%d) empty!",
                        stActCfgData.GetSceneID(),ACT_ID_WORLD_BOSS));
            return 0;
        }
        CSceneCfgData& stSceneCfgData =
            CMainCtrl::m_pstMain->m_stSceneMgr.GetSceneCfg(iIndex);

        _stWorldBossMonster.SetMapID(stSceneCfgData.GetMapID());
    }

    return _stWorldBossMonster.GetMapID();
}

int CWorldBossMgr::InitPlayerData(CPlayerCacheData& stPlayerCache)
{
    int iIndex = 0;
    int iActBeginTime =
        CMainCtrl::m_pstMain->m_stActMgr.GetBeginTime(ACT_ID_WORLD_BOSS);
    bool bMerlin = false;
    bool bInspire = false;
    bool bRoleDead = false;
    bool bRoleCooling = false;

    if (iActBeginTime > stPlayerCache._stWorldBossRole.GetActBeginTime())
    {
        stPlayerCache._stWorldBossRole.Clear();

        stPlayerCache._stWorldBossRole.SetActBeginTime(iActBeginTime);

        stPlayerCache._stWorldBossRole.SetEndTime(
            _stWorldBossMonster.GetEndTime());

        iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
            ACT_ID_WORLD_BOSS);
        CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);
        
        CActStatusCfgData& stActStatusCfg =
            CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, stActStatusCfg.GetDeadID());
        if (iIndex >= 0)
        {
            bRoleDead = true;
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetDeadID(), false);
            WorldBossNotify(stPlayerCache._uiGID, CMD_WORLD_BOSS_SUB_REVIVE,
                true);
        }

        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, stActStatusCfg.GetMerlinID());
        if (iIndex >= 0)
        {
            bMerlin = true;
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetMerlinID(), false);
        }

        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, stActStatusCfg.GetInspireID());
        if (iIndex >= 0)
        {
            bInspire = true;
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetInspireID(), false);
        }

        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, stActStatusCfg.GetCoolingID());
        if (iIndex >= 0)
        {
            bRoleCooling = true;
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetCoolingID(), false);
        }

        if (bMerlin || bInspire || bRoleDead || bRoleCooling)
        {
            if (CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                    stActStatusCfg.GetDeadID()) || 
                CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                    stActStatusCfg.GetMerlinID()) ||
                CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                    stActStatusCfg.GetInspireID()) ||
                CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                    stActStatusCfg.GetCoolingID()))
            {
                CMainCtrl::m_pstMain->m_stStatusMgr.NotifyUserStatusToSelfByGID(
                    stPlayerCache._uiGID);
            }
        }
    }

    return 0;
}

int CWorldBossMgr::GetMerlinGold(CPlayerCacheData& stPlayerCache)
{
    int iGold = WORLD_BOSS_MERLIN_GOLD_INIT +
            (stPlayerCache._stWorldBossRole.GetMerlinTimes() *
                WORLD_BOSS_MERLIN_GOLD_ADD);

    if (iGold > WORLD_BOSS_MERLIN_GOLD_MAX)
    {
        iGold = WORLD_BOSS_MERLIN_GOLD_MAX;
    }
    return iGold;
}

int CWorldBossMgr::GetReviveGold(CPlayerCacheData& stPlayerCache)
{
    int iGold = WORLD_BOSS_DEAD_GOLD_INIT +
            (stPlayerCache._stWorldBossRole.GetDieTimes() *
                WORLD_BOSS_DEAD_GOLD_ADD);
    if (iGold > WORLD_BOSS_DEAD_GOLD_MAX)
    {
        iGold = WORLD_BOSS_DEAD_GOLD_MAX;
    }
    return iGold;
}

//梅林祝福
int CWorldBossMgr::BuyMerlin(CPlayerBaseInfo& stPlayerBase,
        CPlayerCacheData& stPlayerCache, MsgAnsWorldBoss& stAns)
{
    int iRet = 0;
    int iIndex = 0;

    //是否活动开启
    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(ACT_ID_WORLD_BOSS))
    {
        return ERROR_WORLD_BOSS_ACT_NO_OPEN;
    }

    //是否世界BOSS场景
    if (!CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(
            GetWorldBossMapID(), stPlayerBase._uiGID))
    {
        return ERROR_WORLD_BOSS_NOT_IN_MAP;
    }

    //角色状态是否已满
    if (stPlayerCache._stUserStatus.IsUserStatusFull())
    {
        return ERROR_STATUS_UNIT_FULL;
    }

    iRet = InitPlayerData(stPlayerCache);
    CT_RETURN(iRet);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        ACT_ID_WORLD_BOSS);
    CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);
    
    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    //检查状态配置
    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatusCfg(
        stActStatusCfg.GetMerlinID());
    if (iIndex < 0)
    {
        return ERROR_STATUS_EMPTY_CFG;
    }
    CStatusCfgData& stStatusCfg =
        CMainCtrl::m_pstMain->m_stStatusMgr.GetStatusCfg(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetMerlinID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);
        if (stStatusCfg.GetAddMax() > 0 &&
            stStatusUnit.GetAddNum() >= stStatusCfg.GetAddMax())
        {
            return ERROR_STATUS_MAX_ADD_TIMES;
        }
    }

    char chMerlinTimes = stPlayerCache._stWorldBossRole.GetMerlinTimes();
    if (chMerlinTimes < 0)
    {
        CT_WARNING(("role(%u) merlin times error(MerlinTimes=%d)",
                    stPlayerBase._uiGID,chMerlinTimes));
        return ERROR_STATUS_DATA_IN_ROLE;
    }

    int iGold = GetMerlinGold(stPlayerCache);

    //是否金币足够
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stPlayerBase,
        OSS_MONEY_MODULE_32, iGold);
    CHECK_RETURN(iRet);

    CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stPlayerBase._uiGID,
        NOTIFY_USER_MONEY);

    iRet = CMainCtrl::m_pstMain->m_stStatusMgr.AddStatus(
        stPlayerCache, stActStatusCfg.GetMerlinID(),
        _stWorldBossMonster.GetEndTime(), ACT_ID_WORLD_BOSS, true);
    CT_RETURN(iRet);

    stPlayerCache._stWorldBossRole.SetMerlinTimes(chMerlinTimes + 1);

    stAns.set_merlin_gold(GetMerlinGold(stPlayerCache));

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetMerlinID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                  stPlayerCache, iIndex);

        stAns.set_merlin_remain(
            stStatusCfg.GetAddMax() - stStatusUnit.GetAddNum());
    }

    return 0;
}

//鼓舞状态
int CWorldBossMgr::AddInspire(CPlayerCacheData& stPlayerCache)
{
    int iRet = 0;
    int iIndex = 0;

    //是否活动开启
    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(ACT_ID_WORLD_BOSS))
    {
        return ERROR_WORLD_BOSS_ACT_NO_OPEN;
    }

    //是否世界BOSS场景
    if (!CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(
                GetWorldBossMapID(), stPlayerCache._uiGID))
    {
        return ERROR_WORLD_BOSS_NOT_IN_MAP;
    }

    //角色状态是否已满
    if (stPlayerCache._stUserStatus.IsUserStatusFull())
    {
        return ERROR_STATUS_UNIT_FULL;
    }

    iRet = InitPlayerData(stPlayerCache);
    CT_RETURN(iRet);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        ACT_ID_WORLD_BOSS);
    CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);
    
    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    //检查状态配置
    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatusCfg(
        stActStatusCfg.GetInspireID());
    if (iIndex < 0)
    {
        return ERROR_STATUS_EMPTY_CFG;
    }
    CStatusCfgData& stStatusCfg =
        CMainCtrl::m_pstMain->m_stStatusMgr.GetStatusCfg(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetInspireID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);
        if (stStatusCfg.GetAddMax() > 0 &&
            stStatusUnit.GetAddNum() >= stStatusCfg.GetAddMax())
        {
            return ERROR_STATUS_MAX_ADD_TIMES;
        }
    }

    iRet = CMainCtrl::m_pstMain->m_stStatusMgr.AddStatus(
        stPlayerCache, stActStatusCfg.GetInspireID(),
        _stWorldBossMonster.GetEndTime(), ACT_ID_WORLD_BOSS, true);
    CT_RETURN(iRet);

    return 0;
}

//金币复活
int CWorldBossMgr::DeadRevive(CPlayerBaseInfo& stPlayerBase,
        CPlayerCacheData& stPlayerCache, MsgAnsWorldBoss& stAns)
{
    int iRet = 0;
    int iIndex = 0;

    //活动已结束 不能使用此流程清除死亡状态
    if (_stWorldBossMonster.GetEndTime() <= CMainCtrl::m_pstMain->m_iNow)
    {
        return ERROR_WORLD_BOSS_ALREADY_END;
    }

    //是否世界BOSS场景
    if (!CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(
                GetWorldBossMapID(), stPlayerBase._uiGID))
    {
        return ERROR_WORLD_BOSS_NOT_IN_MAP;
    }

    iRet = InitPlayerData(stPlayerCache);
    CT_RETURN(iRet);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        ACT_ID_WORLD_BOSS);
    CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);
    
    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    //处理死亡状态
    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetDeadID());
    if (iIndex < 0)
    {
        return ERROR_WORLD_BOSS_NOT_IN_DEAD;
    }
    CStatusUnit& stStatusUnit = CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
        stPlayerCache, iIndex);

    //死亡状态到期 不扣金子 主动清除
    if (stStatusUnit.GetEndTime() <= CMainCtrl::m_pstMain->m_iNow)
    {
        CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
            stActStatusCfg.GetDeadID(), true);
        WorldBossNotify(stPlayerBase._uiGID, CMD_WORLD_BOSS_SUB_REVIVE, true);
        return ERROR_STATUS_END_NO_EXPEND;
    }

    char chDieTimes = stPlayerCache._stWorldBossRole.GetDieTimes();
    if (chDieTimes < 0)
    {
        CT_WARNING(("role(%u) die times error(DieTimes=%d)",
                    stPlayerBase._uiGID,chDieTimes));
        chDieTimes = 0;
    }

    int iGold = GetReviveGold(stPlayerCache);

    //是否金币足够
    iRet = CMainCtrl::m_pstMain->m_stItemMgr.SubGold(stPlayerBase,
        OSS_MONEY_MODULE_33, iGold);
    CHECK_RETURN(iRet);

    CMainCtrl::m_pstMain->m_stNotifyMgr.Notify(stPlayerBase._uiGID,
        NOTIFY_USER_MONEY);

    //释放死亡状态
    CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
        stActStatusCfg.GetDeadID(), true);

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetCoolingID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);

        //战斗冷却没有叠加层数 直接修改到期时间
        stStatusUnit.SetEndTime(0);
    }

    stPlayerCache._stWorldBossRole.SetDieTimes(chDieTimes + 1);

    stAns.set_revive_gold(GetReviveGold(stPlayerCache));

    WorldBossNotify(stPlayerBase._uiGID, CMD_WORLD_BOSS_SUB_REVIVE, false);

    return 0;
}

//进入战斗
int CWorldBossMgr::WorldBossBattle(CPlayerBaseInfo& stPlayerBase,
        CPlayerDetailInfo& stPlayerDetail, CPlayerOnlineData& stPlayerOnline,
        CPlayerCacheData& stPlayerCache, MsgReqWorldBoss& stReq,
        MsgAnsWorldBoss& stAns, CWorldBossCmdData& stCmdData)
{
    int iRet = 0;
    int iIndex = 0;

    _bFifty = false;
    _bKill = false;
    bool bSceneNotify = false;

    //是否活动开启
    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(ACT_ID_WORLD_BOSS))
    {
        return ERROR_WORLD_BOSS_ACT_NO_OPEN;
    }

    if (CMainCtrl::m_pstMain->m_iNow < _stWorldBossMonster.GetMonsterBornTime())
    {
        return ERROR_WORLD_BOSS_ACT_NO_OPEN;
    }

    //是否世界BOSS场景
    if (!CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(
                _stWorldBossMonster.GetMapID(), stPlayerBase._uiGID))
    {
        return ERROR_WORLD_BOSS_NOT_IN_MAP;
    }

    //是否BOSS已死亡
    int iMonsterHP = _stWorldBossMonster.GetMonsterHP();
    if (iMonsterHP <= 0)
    {
        return ERROR_WORLD_BOSS_ALREADY_END;
    }

    iRet = InitPlayerData(stPlayerCache);
    CT_RETURN(iRet);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActCfg(ACT_ID_WORLD_BOSS);
    CT_CHECK(iIndex, ERROR_ACT_EMPTY_CFG);

    CActCfgData& stActCfgData =
        CMainCtrl::m_pstMain->m_stActMgr.GetActCfg(iIndex);

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        ACT_ID_WORLD_BOSS);
    CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);
    
    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    //是否死亡
    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetDeadID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);
        //死亡状态到期 不扣金子 主动清除
        if (stStatusUnit.GetEndTime() <= CMainCtrl::m_pstMain->m_iNow)
        {
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetDeadID(), true);
            WorldBossNotify(stPlayerBase._uiGID, CMD_WORLD_BOSS_SUB_REVIVE,
                true);
        }
        else
        {
            return ERROR_WORLD_BOSS_ROLE_IN_DEAD;
        }
    }

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetCoolingID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);

        //战斗等待状态到期 先不主动清除 只判断时间
        if (stStatusUnit.GetEndTime() > CMainCtrl::m_pstMain->m_iNow)
        {
            return ERROR_STATUS_IN_FIGHT_CD;
        }
    }

    CMonsterGroupConfigData stMonsterGroup;
    iRet = CMainCtrl::m_pstMain->m_stMonsterConfigMgr.GetMonsterGroupConfig(
        _stWorldBossMonster.GetMonsterGroupID(),
        _stWorldBossMonster.GetWorldLevel(), stMonsterGroup);
    CT_RETURN(iRet);

    MsgBattleResult* pstBattleResult = stAns.mutable_battle_result();
    if (!pstBattleResult)
    {
        return RET_SYS_NULL_POINTER;
    }

    iRet = CMainCtrl::m_pstMain->m_stBattleMgr.DealWorldBoss(stPlayerBase,
        stPlayerDetail, stPlayerOnline, stMonsterGroup, *pstBattleResult,
        stActCfgData.GetType());
    CT_RETURN(iRet);

#if 0
    CTSizeString<64> sTimeInt;
    sTimeInt.Cat("%ld_%ld",CMainCtrl::m_pstMain->m_stNowTime.tv_sec,
            CMainCtrl::m_pstMain->m_stNowTime.tv_usec);
    CMainCtrl::m_pstMain->DumpPBMsgToFile(sTimeInt.Get(), *pstBattleResult);
#endif

	if (stReq.has_battle_ext_info())
	{
		(*pstBattleResult->mutable_battle_ext_info()) =
            stReq.battle_ext_info();
	}

    for (int i = 0; i <
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRoleCount(); ++i)
    {
        CBattleRole& stBattleObj =
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRole(i);
        if (stBattleObj.IsMonsterObject())
        {
            _stWorldBossMonster.AddAtkValue(
                _stWorldBossMonster.GetMonsterHP() - stBattleObj.GetHP());
            break;
        }
    }

    //累加角色攻击伤害
    stPlayerCache._stWorldBossRole.AddAtkValue(
            _stWorldBossMonster.GetAtkValue());

    if (_stWorldBossMonster.GetAtkValue() > 0)
    {
        CMainCtrl::m_pstMain->m_stRewardBackMgr.SetPlayerAct(
            stPlayerBase._uiGID, ACT_ID_WORLD_BOSS);
    }

    //更新排名榜
    if (_stWorldBossMonster.GetAtkValue() > 0 &&
        stPlayerCache._stWorldBossRole.GetAtkValue() > 0)
    {
        CWorldBossAtkUnit stRankUnit;
        int iOldOrder = -1;
        int iNewOrder = -1;
        stRankUnit.SetGID(stPlayerCache._uiGID);
        stRankUnit.SetRoleName(stPlayerBase._sRoleName());
        stRankUnit.SetAcademy(stPlayerBase._ucAcademy);
        stRankUnit.SetAtkValue(stPlayerCache._stWorldBossRole.GetAtkValue());
        _stWorldBossMonster.UpdateRank(stRankUnit, iOldOrder, iNewOrder);

        if ((iNewOrder >= 0 &&
             iNewOrder < CWorldBossMonster::WB_MONSTER_RANK_SHOW_COUNT) ||
            (iNewOrder >= 0 && iOldOrder != iNewOrder))
        {
            bSceneNotify = true;
        }
    }

    for (int i = 0; i <
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRoleCount(); ++i)
    {
        //先处理Boss怪物 如果怪物死亡 活动结束 不需要加主角死亡惩罚
        CBattleRole& stBattleObj =
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRole(i);
        if (stBattleObj.IsMonsterObject())
        {
            iRet = DealMonsterAfterBattle(stPlayerBase, stBattleObj, stCmdData);
            if (iRet){CT_ERROR(("Deal monster after battle error(%d)!",iRet));}
        }
    }

    for (int i = 0; i < CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRoleCount(); ++i)
    {
        //处理主角
        CBattleRole& stBattleObj =
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRole(i);
        if (stBattleObj.IsPlayerObject())
        {
            iRet = DealPlayerAfterBattle(stPlayerBase, stPlayerOnline,
                stPlayerCache, stAns, pstBattleResult->result(), stCmdData);
            if (iRet){CT_ERROR(("Deal player after battle error(%d)!",iRet));}

            break;
        }
    }

    if (bSceneNotify)
    {
        WorldBossNotify();
    }

    return 0;
}

//修正战斗开始前数据
int CWorldBossMgr::ReviseBeforeBattle(int iBossBattleID)
{
    if (iBossBattleID < 0 ||
        iBossBattleID >=
            CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRoleCount())
    {
        return ERROR_BATTLE_GRID_ID;
    }

    _stWorldBossMonster.SetAtkValue(0);

    CBattleRole& stBattleRole =
        CMainCtrl::m_pstMain->m_stBattleMgr.GetBattleRole(iBossBattleID);

    stBattleRole.SetHP(_stWorldBossMonster.GetMonsterHP());

    return 0;
}

int CWorldBossMgr::DealMonsterAfterBattle(CPlayerBaseInfo& stPlayerBase,
        CBattleRole& stBattleObj, CWorldBossCmdData& stCmdData)
{
    int iMonsterHPOld = _stWorldBossMonster.GetMonsterHP();

    //血量结算
    _stWorldBossMonster.SetMonsterHP(stBattleObj.GetHP());

    int iMonsterHPNew = _stWorldBossMonster.GetMonsterHP();

    int iMonsterHPMax = _stWorldBossMonster.GetMonsterHPMax();

    if (_stWorldBossMonster.GetAtkValue() > 0 && iMonsterHPMax > 0)
    {
        int64 i64RatioTmp = INT64_1 * iMonsterHPOld * BATTLE_RATE_SKILL_PERCENT;
        i64RatioTmp /= iMonsterHPMax;
        int iOldHPPec = (int)(i64RatioTmp);

        i64RatioTmp = INT64_1 * iMonsterHPNew * BATTLE_RATE_SKILL_PERCENT;
        i64RatioTmp /= iMonsterHPMax;
        int iNowHPPec = (int)(i64RatioTmp);

#define WORLD_BOSS_REWARD_PERCENT 500      //BOSS击杀奖励百分比

        if (iOldHPPec >= WORLD_BOSS_REWARD_PERCENT &&
            iNowHPPec < WORLD_BOSS_REWARD_PERCENT)
        {
            _bFifty = true;
        }
    }

    //活动处理
    if (_stWorldBossMonster.GetMonsterHP() <= 0)
    {
        _bKill = true;

        //设置击杀者信息
        _stWorldBossMonster.SetKillerGID(stPlayerBase._uiGID);

        //设置世界BOSS关闭时间
        _stWorldBossMonster.SetEndTime(CMainCtrl::m_pstMain->m_iNow);

        stCmdData.SetActClose(true);
    }

    return 0;
}

int CWorldBossMgr::DealPlayerAfterBattle(CPlayerBaseInfo& stPlayerBase,
        CPlayerOnlineData& stPlayerOnline, CPlayerCacheData& stPlayerCache,
        MsgAnsWorldBoss& stAns, int iBattleResult, CWorldBossCmdData& stCmdData)
{
    int iRet = 0;
    int iIndex = 0;

    //奖励结算
    WorldBossRoleReward(stPlayerBase, stAns, stCmdData);

    //活动已经结束
    if (stCmdData.GetActClose())
    {
        return 0;
    }

    //鼓舞状态
    CT_TRACE(("role(%u) world boss attack value(%d) inspire trigger(%d).",
              stPlayerCache._uiGID,_stWorldBossMonster.GetAtkValue(),
              _stWorldBossMonster.GetInspireTrigger()));

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        ACT_ID_WORLD_BOSS);
    CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);
    
    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    if (_stWorldBossMonster.GetAtkValue() >=
            _stWorldBossMonster.GetInspireTrigger())
    {
        //给本地图所有角色增加一层鼓舞状态
        CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
        CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(
            _stWorldBossMonster.GetMapID(), auiMapUserList);

        for (int i = 0; i < auiMapUserList.Size(); ++i)
        {
            iIndex = CMainCtrl::m_pstMain->FindPlayerCacheData(
                auiMapUserList[i]);
            if (iIndex >= 0)
            {
                CPlayerCacheData& stPlayerCache =
                  CMainCtrl::m_pstMain->m_stPlayerCacheDataHash[iIndex];
                iRet = AddInspire(stPlayerCache);
                CT_TRACE(("Role(%u) add inspire status ret(%d).",
                          auiMapUserList[i],iRet));
            }
            else
            {
                CT_WARNING(("Role(%u) in world boss map(%d) but " \
                            "cache data empty!", auiMapUserList[i],
                            _stWorldBossMonster.GetMapID()));
            }
        }
    }

    if (BATTLE_RESULT_WIN != iBattleResult)
    {
        stPlayerOnline._usMapPosX = -1;             
        stPlayerOnline._usMapPosY = -1;

        //死亡状态没有叠加层数 直接修改到期时间
        iRet = CMainCtrl::m_pstMain->m_stStatusMgr.AddStatus(
            stPlayerCache, stActStatusCfg.GetDeadID(),
            CMainCtrl::m_pstMain->m_iNow + WORLD_BOSS_DEAD_WAIT_TIME,
            ACT_ID_WORLD_BOSS, false);
        if (iRet) {CT_ERROR(("role add dead status error(%d)",iRet));}

        WorldBossNotify(stPlayerCache._uiGID, CMD_WORLD_BOSS_SUB_DEAD, true);

        //战斗冷却没有叠加层数 直接修改到期时间
        iRet = CMainCtrl::m_pstMain->m_stStatusMgr.AddStatus(
            stPlayerCache, stActStatusCfg.GetCoolingID(),
            CMainCtrl::m_pstMain->m_iNow + WORLD_BOSS_FIGHT_WAIT_TIME,
            ACT_ID_WORLD_BOSS, false);
        if (iRet) {CT_ERROR(("role add fight cool status error(%d)",iRet));}

        if (CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                stActStatusCfg.GetDeadID()) || 
            CMainCtrl::m_pstMain->m_stStatusMgr.IsNeedSendStatusList(
                stActStatusCfg.GetCoolingID()))
        {
            CMainCtrl::m_pstMain->m_stStatusMgr.NotifyUserStatusToSelfByGID(
                stPlayerCache._uiGID);
        }
    }

    MsgAnsWorldBoss stMsgAnsWB;
    GetWorldBossMonster(stMsgAnsWB);//怪物血量
    GetWorldBossAtkRank(stMsgAnsWB);//伤害排名
    GetWorldBossRole(stPlayerCache, stMsgAnsWB);
    WorldBossNotify(stPlayerCache._uiGID, CMD_WORLD_BOSS_SUB_ATK_RANK,
        stMsgAnsWB);

    _stWorldBossMonster.SetLastNotifyGID(stPlayerCache._uiGID);

    unsigned int uiRoleGID = 0;

    for (int i = 0; i < _stWorldBossMonster.GetRankSize() &&
           i < CWorldBossMonster::WB_MONSTER_RANK_SHOW_COUNT; ++i)
    {
        CWorldBossAtkUnit& stAtkUnit = _stWorldBossMonster.GetRankUnit(i);
        uiRoleGID = stAtkUnit.GetGID();
        if (uiRoleGID == stPlayerCache._uiGID)
        {
            continue;
        }

        //是否世界BOSS场景
        if (!CMainCtrl::m_pstMain->m_stMapViews.IsRoleInMap(
                GetWorldBossMapID(), uiRoleGID))
        {
            continue;
        }

        iIndex = CMainCtrl::m_pstMain->FindPlayerCacheData(uiRoleGID);
        if (iIndex < 0)
        {
            CT_WARNING(("role(%u) in world boss rank but cache data empty!",
                        uiRoleGID));
            continue;
        }
        CPlayerCacheData& stPlayerCacheTmp =
            CMainCtrl::m_pstMain->m_stPlayerCacheDataHash[iIndex];

        GetWorldBossRole(stPlayerCacheTmp, stMsgAnsWB);

        WorldBossNotify(stPlayerCacheTmp._uiGID, CMD_WORLD_BOSS_SUB_ATK_RANK,
            stMsgAnsWB);
    }

    return 0;
}

int CWorldBossMgr::GMDealWorldBoss(CPlayerDetailInfo& stPlayerDetail,
        MsgReqGMPlayer& stReq, MsgAnsGMPlayer& stAns)
{
    int iRet = 0;
    int iIndex = 0;
    CTSizeString<MAX_BATTLE_NAME_BUFF> szNameStr;

    switch (stReq.sub_type())
    {
    case ID_GM_PLAYER_SUB_GET_WORLD_BOSS_RANK:
        {
            iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
                ACT_ID_WORLD_BOSS);
            CT_CHECK(iIndex, ERROR_ACT_STATUS_EMPTY_CFG);
            
            CActStatusCfgData& stActStatusCfg =
                CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

            szNameStr.Cat("结束时间:%d ",_stWorldBossMonster.GetEndTime());
            szNameStr.Cat("世界等级:%d ",_stWorldBossMonster.GetWorldLevel());
            szNameStr.Cat("场景ID:%u ",GetWorldBossMapID());
            szNameStr.Cat("活动ID:%d ",ACT_ID_WORLD_BOSS);
            szNameStr.Cat("死亡:%d ",stActStatusCfg.GetDeadID());
            szNameStr.Cat("冷却:%d ",stActStatusCfg.GetCoolingID());
            szNameStr.Cat("祝福:%d ",stActStatusCfg.GetMerlinID());
            szNameStr.Cat("鼓舞:%d ",stActStatusCfg.GetInspireID());
            
            szNameStr.Cat("\nBOSS出生时间:%d BOSS:%d/%d",
                          _stWorldBossMonster.GetMonsterBornTime(),
                          _stWorldBossMonster.GetMonsterHP(),
                          _stWorldBossMonster.GetMonsterHPMax());

            szNameStr.Cat("\n世界BOSS排名榜总数:%d",
                          _stWorldBossMonster.GetRankSize());

            for (int i = 0; i < _stWorldBossMonster.GetRankSize(); ++i)
            {
                CWorldBossAtkUnit& stRankUnit =
                    _stWorldBossMonster.GetRankUnit(i);
                szNameStr.Cat("\nGID:%u ",stRankUnit.GetGID());
                szNameStr.Cat("%s ",stRankUnit.GetRoleName());
                szNameStr.Cat("伤害:%d",stRankUnit.GetAtkValue());
            }

            stAns.set_name(szNameStr.Get());
        }
        break;
    case ID_GM_PLAYER_SUB_SET_BOSS_WORLD_LEVEL:
        {
            if (stReq.datas_size() < 2)
            {
                return 0;
            }

            short shActID = (short)stReq.datas(0);
            int iNewLevel = stReq.datas(1);

            if (iNewLevel < 14)
            {
                iNewLevel = 14;
            }
            else if (iNewLevel > MAX_ROLE_LEVEL)
            {
                iNewLevel = MAX_ROLE_LEVEL; 
            }

            switch (shActID)
            {
            case ACT_ID_WORLD_BOSS: //世界BOSS活动ID
                {
                    _stWorldBossMonster.SetWorldLevel(iNewLevel);
                }
                break;
            case ACT_ID_GRAN_BOSS: //格兰学院BOSS活动ID
            case ACT_ID_SLEN_BOSS: //斯林学院BOSS活动ID
            case ACT_ID_RAVAN_BOSS: //拉文学院BOSS活动ID
            case ACT_ID_HUFF_BOSS: //霍奇学院BOSS活动ID
                {
                    iRet =
                      CMainCtrl::m_pstMain->m_stAcademyBossMgr.GMSetWorldLevel(
                            shActID, iNewLevel);
                }
                break;
            case ACT_ID_MAGIC_DOOR: //魔界传送门
                {

                }
                break;
            default:
                return ERROR_MAIN_SUB_CMD;
            }
        }
        break;
    case ID_GM_PLAYER_SUB_SET_BOSS_MONSTER_HP:
        {
            if (stReq.datas_size() < 2)
            {
                return 0;
            }

            short shActID = (short)stReq.datas(0);
            int iNewHP = stReq.datas(1);
            int iMonsterType = 0;

            if (iNewHP < 0)
            {
                iNewHP = 0;
            }

            switch (shActID)
            {
            case ACT_ID_WORLD_BOSS: //世界BOSS活动ID
                {
                    _stWorldBossMonster.SetMonsterHP(iNewHP);
                }
                break;
            case ACT_ID_GRAN_BOSS: //格兰学院BOSS活动ID
            case ACT_ID_SLEN_BOSS: //斯林学院BOSS活动ID
            case ACT_ID_RAVAN_BOSS: //拉文学院BOSS活动ID
            case ACT_ID_HUFF_BOSS: //霍奇学院BOSS活动ID
                {
                    if (stReq.datas_size() < 3)
                    {
                        return ERROR_MAIN_SUB_CMD;
                    }
                    iMonsterType = stReq.datas(2);
                    iRet =
                      CMainCtrl::m_pstMain->m_stAcademyBossMgr.GMSetMonsterHP(
                            shActID, iNewHP, iMonsterType);
                }
                break;
            case ACT_ID_MAGIC_DOOR: //魔界传送门
                {
                    if (stReq.datas_size() < 3)
                    {
                        return ERROR_MAIN_SUB_CMD;
                    }
                    iMonsterType = stReq.datas(2);
                    iRet =
                        CMainCtrl::m_pstMain->m_stMagicDoorMgr.GMSetMonsterHP(
                            stPlayerDetail, iNewHP, iMonsterType);
                }
                break;
            default:
                return ERROR_MAIN_SUB_CMD;
            }
        }
        break;
    default:
        return ERROR_MAIN_SUB_CMD;
    }

    return iRet;
}

void CWorldBossMgr::WorldBossNotify()
{
    int iIndex = 0;
    if (CMainCtrl::m_pstMain->m_iNow < _stWorldBossMonster.GetLastNotify())
    {
        return;
    }

    //活动已经结束
    if (!CMainCtrl::m_pstMain->m_stActMgr.IsActOpen(ACT_ID_WORLD_BOSS))
    {
        return;
    }

    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
    CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(
        _stWorldBossMonster.GetMapID(), auiMapUserList);

    if (auiMapUserList.Size() <= 0)
    {
        return;
    }

    MsgAnsWorldBoss stMsgAnsWB;
    GetWorldBossMonster(stMsgAnsWB);//怪物血量
    GetWorldBossAtkRank(stMsgAnsWB);//伤害排名

    for (int i = 0; i < auiMapUserList.Size(); ++i)
    {
        iIndex = CMainCtrl::m_pstMain->FindPlayerCacheData(auiMapUserList[i]);
        if (iIndex < 0)
        {
            CT_WARNING(("Role(%u) in world boss map(%d) but " \
                        "cache data empty!", auiMapUserList[i],
                        _stWorldBossMonster.GetMapID()));
            continue;
        }

        CPlayerCacheData& stPlayerCache =
            CMainCtrl::m_pstMain->m_stPlayerCacheDataHash[iIndex];

        iIndex = _stWorldBossMonster.GetRankRoleOrder(auiMapUserList[i]);
        if (iIndex >= 0 &&
            iIndex < CWorldBossMonster::WB_MONSTER_RANK_SHOW_COUNT)
        {
            continue;
        }

        if (_stWorldBossMonster.GetLastNotifyGID() == auiMapUserList[i])
        {
            continue;
        }

        GetWorldBossRole(stPlayerCache, stMsgAnsWB);
        WorldBossNotify(stPlayerCache._uiGID, CMD_WORLD_BOSS_SUB_ATK_RANK,
            stMsgAnsWB);
    }

    _stWorldBossMonster.SetLastNotify(
        CMainCtrl::m_pstMain->m_iNow + WORLD_BOSS_NOTIFY_WAIT_TIME);
}

void CWorldBossMgr::WorldBossNotify(unsigned int uiGID, int iSubCmd,
        bool bNotifySelf)
{
    int iIndex = 0;
    short shStatusID = 0;
    int iExpTime = 0;
    MsgAnsWorldBoss stAns;

    iIndex = CMainCtrl::m_pstMain->FindPlayerCacheData(uiGID);
    if (iIndex < 0)
    {
        CT_WARNING(("no cache data user(%u)",uiGID));
        return;
    }
	CPlayerCacheData& stPlayerCache =
        CMainCtrl::m_pstMain->m_stPlayerCacheDataHash[iIndex];

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        ACT_ID_WORLD_BOSS);
    if (iIndex < 0){return;}
    
    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    //注意都需要同步给同场景内的其他角色
    switch (iSubCmd)
    {
#if 0 //状态图标只需要提示给自己 有响应包返回 暂不需要下发其他角色
    case CMD_WORLD_BOSS_SUB_BUFF://购买梅林的祝福状态
        {
            shStatusID = stActStatusCfg.GetMerlinID();
        }
        break;
    case CMD_WORLD_BOSS_SUB_INSPIRE://施加鼓舞状态
        {
            shStatusID = stActStatusCfg.GetInspireID();
        }
        break;
#endif
    case CMD_WORLD_BOSS_SUB_REVIVE://金币复活
        break;
    case CMD_WORLD_BOSS_SUB_DEAD://角色死亡
        {
            shStatusID = stActStatusCfg.GetDeadID();
        }
        break;
    default:
        return;
    }

    if (shStatusID > 0)
    {
        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, shStatusID);
        if (iIndex < 0)
        {
            CT_WARNING(("role(%u) doesn't have status(%d)",stPlayerCache._uiGID,
                        shStatusID));
            return;
        }

        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(stPlayerCache,iIndex);

        iExpTime = stStatusUnit.GetEndTime();
    }

    stAns.set_sub_type(iSubCmd);
    stAns.set_gid((int)uiGID);
    stAns.set_expire_time(iExpTime);

    PBMsgHead stMsgHead;
    stMsgHead.set_version(0);
    stMsgHead.set_time(CMainCtrl::m_pstMain->m_iNow);
    stMsgHead.set_msgact(0);
    stMsgHead.set_msgid(ID_MAIN_WORLD_BOSS);
    stMsgHead.set_msgret(0);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    CMainCtrl::m_pstMain->m_stEncodeBuf.Clear();
    CMainCtrl::m_pstMain->EncodePBMsg(stMsgHead,
        CMainCtrl::m_pstMain->m_stEncodeBuf);
    CMainCtrl::m_pstMain->EncodePBMsg(stAns,
        CMainCtrl::m_pstMain->m_stEncodeBuf);

    if (bNotifySelf)
    {
        CMainCtrl::m_pstMain->NotifyOnlineUser(uiGID,
            CMainCtrl::m_pstMain->m_stEncodeBuf);
    }

    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
    CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(
        _stWorldBossMonster.GetMapID(), auiMapUserList);
    
    for (int i = 0; i < auiMapUserList.Size(); ++i)
    {
        if (auiMapUserList[i] != uiGID)
        {
            CMainCtrl::m_pstMain->NotifyOnlineUser(auiMapUserList[i],
                CMainCtrl::m_pstMain->m_stEncodeBuf);
        }
    }
}

void CWorldBossMgr::WorldBossNotify(unsigned int uiGID, int iSubCmd,
        MsgAnsWorldBoss& stAns)
{
    switch (iSubCmd)
    {
    case CMD_WORLD_BOSS_SUB_DEAD://角色死亡
        {
            CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
            CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(
                _stWorldBossMonster.GetMapID(), auiMapUserList);
            
            stAns.set_sub_type(iSubCmd);
            stAns.set_gid((int)uiGID);
            for (int i = 0; i < auiMapUserList.Size(); ++i)
            {
                CMainCtrl::m_pstMain->NotifyOnlineUser(auiMapUserList[i],
                    ID_MAIN_WORLD_BOSS, stAns, false);
            }
        }
        break;
    case CMD_WORLD_BOSS_SUB_ATK_RANK://怪物血量+攻击伤害榜+主角名次及攻击伤害
        {
            stAns.set_gid((int)uiGID);
            stAns.set_sub_type(iSubCmd);
            CMainCtrl::m_pstMain->NotifyOnlineUser(uiGID, ID_MAIN_WORLD_BOSS,
                stAns, false);
        }
        break;
    default:
        break;
    }
}

void CWorldBossMgr::WorldBossSceneNotify()
{
    int iRet = 0;
    int iIndex = 0;

    //本地图所有角色死亡状态清除
    CSingleMapView::MAP_VIEW_NOTIFY_USERS_ARRAY auiMapUserList;
    CMainCtrl::m_pstMain->m_stMapViews.GetAllMapUsers(
        _stWorldBossMonster.GetMapID(), auiMapUserList);
    if (auiMapUserList.Size() <= 0)
    {
        return;
    }

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        ACT_ID_WORLD_BOSS);
    if (iIndex < 0) {return;}
    
    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    MsgAnsWorldBoss stMsgAnsWB;
    GetWorldBossMonster(stMsgAnsWB);//怪物血量
    GetWorldBossKillerInfo(stMsgAnsWB);//怪物击杀者
    GetWorldBossAtkRank(stMsgAnsWB);//伤害排名

    //下发场景内所有在线角色
    for (int i = 0; i < auiMapUserList.Size(); ++i)
    {
        iIndex = CMainCtrl::m_pstMain->FindPlayerCacheData(
            auiMapUserList[i]);
        if (iIndex >= 0)
        {
            CPlayerCacheData& stPlayerCache =
                CMainCtrl::m_pstMain->m_stPlayerCacheDataHash[iIndex];

            iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
                stPlayerCache, stActStatusCfg.GetDeadID());
            if (iIndex >= 0) //清除死亡状态
            {
                CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(
                    stPlayerCache, stActStatusCfg.GetDeadID(), true);

                WorldBossNotify(stPlayerCache._uiGID, CMD_WORLD_BOSS_SUB_REVIVE,
                    true);

                CT_TRACE(("Role(%u) delete dead status ret(%d).",
                          auiMapUserList[i],iRet));
            }

            //下发排名榜
            GetWorldBossRole(stPlayerCache, stMsgAnsWB);

            WorldBossNotify(stPlayerCache._uiGID,
                CMD_WORLD_BOSS_SUB_ATK_RANK, stMsgAnsWB);
        }
        else
        {
            CT_WARNING(("Role(%u) in world boss map(%d) but cache data empty!",
                        auiMapUserList[i],_stWorldBossMonster.GetMapID()));
        }
    }
}

void CWorldBossMgr::WorldBossNotifyTips(int iTipType)
{
    MsgTips stTips;
    stTips.set_type(iTipType);

#define TIPS_WORLD_BOSS_RANK_NUM 3

    switch (iTipType) 
    {
    case TIPS_WORLD_BOSS_RANK://世界BOSS伤害排名提示
        {
            if (_stWorldBossMonster.GetRankSize() <= 0)
            {
                return;
            }
            //顺序为 玩家1 玩家2 玩家3
            for (int i = 0; i < _stWorldBossMonster.GetRankSize() &&
                    i < TIPS_WORLD_BOSS_RANK_NUM; ++i)
            {
                CWorldBossAtkUnit& stAtkUnit =
                     _stWorldBossMonster.GetRankUnit(i);
                stTips.add_tip_argument(stAtkUnit.GetRoleName());
            }
        }
        break;
    default:
        {
            CT_ERROR(("world boss notify tip unknow type(%d)",iTipType));
            return;
        }
    }

    CMainCtrl::m_pstMain->SendOnlineTips(stTips);
}

void CWorldBossMgr::WorldBossNotifyTips(int iTipType, int iSilver, int iRepu,
        CPlayerBaseInfo& stPlayerBase)
{
    CTSizeString<ROLENAME_LEN> szNameStr;
    MsgTips stTips;
    stTips.set_type(iTipType);

    switch (iTipType) 
    {
    case TIPS_WORLD_BOSS_FIFTY://世界BOSS伤害50%时提示
    case TIPS_WORLD_BOSS_KILL_BOSS://世界BOSS击杀提示
        {
            szNameStr.Set("%d",stPlayerBase._ucAcademy);
            stTips.add_tip_argument(szNameStr());
            stTips.add_tip_argument(stPlayerBase._sRoleName());
            szNameStr.Set("%d",iSilver);
            stTips.add_tip_argument(szNameStr());
            szNameStr.Set("%d",iRepu);
            stTips.add_tip_argument(szNameStr());
        }
        break;
    default:
        {
            CT_ERROR(("world boss notify tip unknow type(%d)",iTipType));
            return;
        }
    }

    CMainCtrl::m_pstMain->SendOnlineTips(stTips);
}

void CWorldBossMgr::GetWorldBossMonster(MsgAnsWorldBoss& stAns)
{
    MsgWorldBossMonster* pstMsgMonster = stAns.mutable_monster_info();
    if (!pstMsgMonster)
    {
        CT_WARNING(("MsgWorldBossMonster pointer null!"));
        return;
    }

    pstMsgMonster->set_max_hp(_stWorldBossMonster.GetMonsterHPMax());
    pstMsgMonster->set_level(_stWorldBossMonster.GetWorldLevel());
    pstMsgMonster->set_born_time(_stWorldBossMonster.GetMonsterBornTime());
    pstMsgMonster->set_group_id(_stWorldBossMonster.GetMonsterGroupID());

    //应策划要求当怪物血量下降到一定比例时返回固定值给前端
    int iMonHPNow = _stWorldBossMonster.GetMonsterHP();
    int iMonHPMax = _stWorldBossMonster.GetMonsterHPMax();
    pstMsgMonster->set_now_hp(iMonHPNow);
    if (iMonHPNow > 0 && iMonHPNow < iMonHPMax)
    {
        int64 i64RatioTmp = INT64_1 * iMonHPNow * BATTLE_RATE_SKILL_PERCENT;
        i64RatioTmp /= iMonHPMax;
        int iHPPercent = (int)(i64RatioTmp);

#define WORLD_BOSS_MONSTER_BLOCK_PER 200      //BOSS血量隐藏千分比
#define WORLD_BOSS_MONSTER_BLOCK_NUM 1        //BOSS血量隐藏时此固定值给前端

        if (iHPPercent <= WORLD_BOSS_MONSTER_BLOCK_PER)
        {
            pstMsgMonster->set_now_hp(WORLD_BOSS_MONSTER_BLOCK_NUM);
        }
    }
}

void CWorldBossMgr::GetWorldBossKillerInfo(MsgAnsWorldBoss& stAns)
{
    int iIndex = 0;
    unsigned int uiKillerGID = _stWorldBossMonster.GetKillerGID();
    if (uiKillerGID <= 0)
    {
        return;
    }

    iIndex = CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash.HashFind(uiKillerGID);
    if (iIndex < 0)
	{
        CT_ERROR(("world boss killer no base data user(%u)",uiKillerGID));
        return;
	}
	CPlayerBaseInfo& stPlayerBase =
        CMainCtrl::m_pstMain->m_stPlayerBaseInfoHash[iIndex];

    MsgWorldBossKiller* pstMsgKiller = stAns.mutable_killer_info();
    if (!pstMsgKiller)
    {
        CT_WARNING(("MsgWorldBossKiller pointer null!"));
        return;
    }

    pstMsgKiller->set_killer_gid(stPlayerBase._uiGID);
    pstMsgKiller->set_role_name(stPlayerBase._sRoleName());
}

void CWorldBossMgr::GetWorldBossRole(CPlayerCacheData& stPlayerCache,
        MsgAnsWorldBoss& stAns)
{
    int iIndex = 0;

    stAns.clear_expire_time();//此值专表示死亡到期时间

    stAns.set_gid((int)stPlayerCache._uiGID);
    stAns.set_merlin_gold(GetMerlinGold(stPlayerCache));
    stAns.set_revive_gold(GetReviveGold(stPlayerCache));
    stAns.set_role_order(
        _stWorldBossMonster.GetRankRoleOrder(stPlayerCache._uiGID) + 1);
    stAns.set_role_attack(stPlayerCache._stWorldBossRole.GetAtkValue());
    stAns.set_end_time(_stWorldBossMonster.GetEndTime());

    iIndex = CMainCtrl::m_pstMain->m_stActMgr.FindActStatusCfg(
        ACT_ID_WORLD_BOSS);
    if (iIndex < 0){return;}
    
    CActStatusCfgData& stActStatusCfg =
        CMainCtrl::m_pstMain->m_stActMgr.GetActStatusCfg(iIndex);

    //处理死亡状态
    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
        stPlayerCache, stActStatusCfg.GetDeadID());
    if (iIndex >= 0)
    {
        CStatusUnit& stStatusUnit =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                stPlayerCache, iIndex);

        //死亡状态到期 主动清除
        if (stStatusUnit.GetEndTime() <= CMainCtrl::m_pstMain->m_iNow)
        {
            CMainCtrl::m_pstMain->m_stStatusMgr.DelStatus(stPlayerCache,
                stActStatusCfg.GetDeadID(), true);
        }
        else
        {
            stAns.set_expire_time(stStatusUnit.GetEndTime());
        }
    }

    iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatusCfg(
        stActStatusCfg.GetMerlinID());
    if (iIndex >= 0)
    {
        CStatusCfgData& stStatusCfg =
            CMainCtrl::m_pstMain->m_stStatusMgr.GetStatusCfg(iIndex);

        iIndex = CMainCtrl::m_pstMain->m_stStatusMgr.FindStatus(
            stPlayerCache, stActStatusCfg.GetMerlinID());
        if (iIndex >= 0)
        {
            CStatusUnit& stStatusUnit =
                CMainCtrl::m_pstMain->m_stStatusMgr.GetStatus(
                    stPlayerCache, iIndex);
        
            stAns.set_merlin_remain(
                stStatusCfg.GetAddMax() - stStatusUnit.GetAddNum());
        }
        else
        {
            stAns.set_merlin_remain(stStatusCfg.GetAddMax());
        }
    }
}

void CWorldBossMgr::GetWorldBossAtkRank(MsgAnsWorldBoss& stAns)
{
    stAns.clear_attack_rank();

    for (int i = 0; i < _stWorldBossMonster.GetRankSize() &&
            i < CWorldBossMonster::WB_MONSTER_RANK_SHOW_COUNT; ++i)
    {
        CWorldBossAtkUnit& stAtkUnit = _stWorldBossMonster.GetRankUnit(i);
        MsgWorldBossAtkRank* pstMsgAtkRank = stAns.add_attack_rank();
        if (pstMsgAtkRank)
        {
            stAtkUnit.GetAtkRankUnit(*pstMsgAtkRank);
        }
    }

    stAns.set_end_time(_stWorldBossMonster.GetEndTime());
}

int CWorldBossMgr::GetWorldBossSceneInfo(CPlayerCacheData& stPlayerCache,
        MsgAnsWorldBoss& stAns)
{
    InitPlayerData(stPlayerCache);
    GetWorldBossRole(stPlayerCache, stAns);
    GetWorldBossMonster(stAns);//怪物血量
    GetWorldBossAtkRank(stAns);//伤害排名
    return 0;
}

int CWorldBossMgr::WorldBossRewardItem(unsigned int uiGID, int iRepu, int iExp,
        int iContri, int iSilver, CDropItem& stDropItem)
{
    if (iRepu > 0)
    {
        stDropItem.DropItem(ITEM_TYPE_REPUTATION, iRepu);
    }

    if (iExp > 0)
    {
        stDropItem.DropItem(ITEM_TYPE_EXP, iExp);
    }

    if (iContri > 0)
    {
        stDropItem.DropItem(ITEM_TYPE_CONTRIBUTION, iContri);
    }

    if (iSilver > 0)
    {
        stDropItem.DropItem(ITEM_TYPE_SILVER, iSilver);
    }

    if (stDropItem.Size() > 0)
    {
        stDropItem.SetOssModule(OSS_MODULE_WLDBOSS);
        CMainCtrl::m_pstMain->m_stItemMgr.DropItem(NULL, uiGID, stDropItem);
    }

    return 0;
}

int CWorldBossMgr::WorldBossRoleReward(CPlayerBaseInfo& stPlayerBase,
        MsgAnsWorldBoss& stAns, CWorldBossCmdData& stCmdData)
{
    int iIndex = 0;
    int iTotalExp = 0;
    int iTotalRepu = 0;
    int iTotalContri = 0;
    int iTotalSilver = 0;

    if (_stWorldBossMonster.GetAtkValue() <= 0 ||
        _stWorldBossMonster.GetMonsterHPMax() <= 0)
    {
        return 0;
    }

    int64 i64RatioTmp =
        INT64_1 * _stWorldBossMonster.GetAtkValue() * BATTLE_RATE_SKILL_PERCENT;
    i64RatioTmp /= _stWorldBossMonster.GetMonsterHPMax();
    int iAttackValue = (int)(i64RatioTmp);
    if (iAttackValue <= 0)
    {
        iAttackValue = 1;
    }

    iIndex = _stWorldBossCfg.FindAttackConfig(iAttackValue);
    if (iIndex < 0)
    {
        CT_WARNING(("boss attack hp(%d) max hp(%d) attack id(%d) but cfg empty",
                    _stWorldBossMonster.GetAtkValue(),
                    _stWorldBossMonster.GetMonsterHPMax(),iAttackValue));
        return 0;
    }

    CWorldBossCfgAttack& stAttackCfg = _stWorldBossCfg.GetAttackConfig(iIndex);

    iIndex = _stWorldBossCfg.FindRewardConfig(
            _stWorldBossMonster.GetWorldLevel());
    if (iIndex < 0)
    {
        CT_WARNING(("reward level(%d) config empty",
                    _stWorldBossMonster.GetWorldLevel()));
        return 0;
    }

    CWorldBossCfgReward& stRewardCfg = _stWorldBossCfg.GetRewardConfig(iIndex);

    i64RatioTmp = INT64_1 * stAttackCfg.GetReputationBase() *
        stRewardCfg.GetReputationRatio();
    i64RatioTmp /= BATTLE_RATE_SKILL_PERCENT;
    int iReputation = (int)(i64RatioTmp);

    i64RatioTmp = INT64_1 * stAttackCfg.GetExpBase() *
        stRewardCfg.GetExpRatio();
    i64RatioTmp /= BATTLE_RATE_SKILL_PERCENT;
    int iBattleExp = (int)(i64RatioTmp);

    i64RatioTmp = INT64_1 * stAttackCfg.GetContribuBase() *
        stRewardCfg.GetContribuRatio();
    i64RatioTmp /= BATTLE_RATE_SKILL_PERCENT;
    int iContribu = (int)(i64RatioTmp);

    i64RatioTmp = INT64_1 * stAttackCfg.GetSilverBase() *
        stRewardCfg.GetSilverRatio();
    i64RatioTmp /= BATTLE_RATE_SKILL_PERCENT;
    int iSilver = (int)(i64RatioTmp);

    CT_TRACE(("%d %d %d|%d %d %d|%d %d %d|%d %d %d|%d %d %d",
        _stWorldBossMonster.GetAtkValue(),_stWorldBossMonster.GetMonsterHPMax(),
        iAttackValue,iReputation,stAttackCfg.GetReputationBase(),
        stRewardCfg.GetReputationRatio(),iBattleExp,stAttackCfg.GetExpBase(),
        stRewardCfg.GetExpRatio(),iContribu,stAttackCfg.GetContribuBase(),
        stRewardCfg.GetContribuRatio(),iSilver,stAttackCfg.GetSilverBase(),
        stRewardCfg.GetSilverRatio()));

    iTotalExp += iBattleExp > 0 ? iBattleExp : 0;
    iTotalRepu += iReputation > 0 ? iReputation : 0;
    iTotalContri += iContribu > 0 ? iContribu : 0;
    iTotalSilver += iSilver > 0 ? iSilver : 0;

    if (_bFifty)
    {
        iReputation = stRewardCfg.GetFiftyReputation();
        iBattleExp = stRewardCfg.GetFiftyExp();
        iContribu = stRewardCfg.GetFiftyContribu();
        iSilver = stRewardCfg.GetFiftySilver();

        iTotalExp += iBattleExp > 0 ? iBattleExp : 0;
        iTotalRepu += iReputation > 0 ? iReputation : 0;
        iTotalContri += iContribu > 0 ? iContribu : 0;
        iTotalSilver += iSilver > 0 ? iSilver : 0;

        stCmdData.SetFiftyKill(true);
        stCmdData.SetFiftySilver(iSilver);
        stCmdData.SetFiftyRepu(iReputation);
    }

    if (_bKill)
    {
        iReputation = stRewardCfg.GetKillReputation();
        iBattleExp = stRewardCfg.GetKillExp();
        iContribu = stRewardCfg.GetKillContribu();
        iSilver = stRewardCfg.GetKillSilver();

        iTotalExp += iBattleExp > 0 ? iBattleExp : 0;
        iTotalRepu += iReputation > 0 ? iReputation : 0;
        iTotalContri += iContribu > 0 ? iContribu : 0;
        iTotalSilver += iSilver > 0 ? iSilver : 0;

        stCmdData.SetDeadKill(true);
        stCmdData.SetDeadSilver(iSilver);
        stCmdData.SetDeadRepu(iReputation);
    }

    CDropItem stDropItem;
    WorldBossRewardItem(stPlayerBase._uiGID, iTotalRepu, iTotalExp,
        iTotalContri, iTotalSilver, stDropItem);

    stDropItem.GetPBMsg(stPlayerBase._uiGID, *(stAns.mutable_battle_award()));

    CTSizeString<ROLENAME_LEN> szNameStr;
    MsgTips stTips;
    stTips.set_type(TIPS_WORLD_BOSS_BONUS);
    szNameStr.Set("%d",_stWorldBossMonster.GetAtkValue());//伤害
    stTips.add_tip_argument(szNameStr());
    stDropItem.GetPBMsg(stPlayerBase._uiGID, *(stTips.mutable_bonus()));

    CMainCtrl::m_pstMain->NotifyOnlineUser(stPlayerBase._uiGID, ID_MAIN_TIPS,
        stTips, false);

    return 0;
}

int CWorldBossMgr::WorldBossFinishReward ()
{
    int iRet = 0;
    int iIndex = 0;
    iIndex = _stWorldBossCfg.FindRewardConfig(
        _stWorldBossMonster.GetWorldLevel());
    if (iIndex < 0)
    {
        CT_WARNING(("reward level(%d) config empty",
                    _stWorldBossMonster.GetWorldLevel()));
        return 0;
    }

    CWorldBossCfgReward& stRewardCfg = _stWorldBossCfg.GetRewardConfig(iIndex);

    unsigned int uiGiftID = 0;
    for (int i = 0; i < _stWorldBossMonster.GetRankSize() &&
            i < stRewardCfg.GetGiftSize(); ++i)
    {
        CWorldBossAtkUnit& stAtkUnit = _stWorldBossMonster.GetRankUnit(i);
        uiGiftID = (unsigned int)stRewardCfg.GetGiftID(i);

        CT_TRACE(("world boss reward atk rank(%d) role(%u) gift(%u)",
                  i,stAtkUnit.GetGID(),uiGiftID));
        if (uiGiftID > 0)
        {
            iRet = CMainCtrl::m_pstMain->m_stItemMgr.DropBonus(OSS_MODULE_WLDBOSS,
                stAtkUnit.GetGID(), uiGiftID, 1);
            if (iRet)
            {
                CT_ERROR(("world boss send role(%u) gift(%u) error(%d)",
                    stAtkUnit.GetGID(),uiGiftID,iRet));
            }
        }
    }

    if (_stWorldBossMonster.GetRankSize() > 0)
    {
        int iExpiredTime = CMainCtrl::m_pstMain->m_iNow + 86400;
        
        CMainCtrl::m_pstMain->m_stRoleMgr.DropTitle(
            _stWorldBossMonster.GetRankUnit(0).GetGID(), ROLE_TITLE_WLDBOSS,
            iExpiredTime);
    }

    return 0;
}
